﻿<!DOCTYPE html>
<html>
<head>
	<meta http-equiv="X-UA-Compatible" content="IE=edge" />
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
	<title>File Explorer</title>
	<link rel="icon" type="image/png" href="css/favicon.png" />
	<link type="text/css" href="./css/style.css" rel="stylesheet" />
	<link href="css/prettify.css" type="text/css" rel="stylesheet" />
	<script src="js/jquery-1.8.3.min.js"></script>
	<script type="text/javascript" src="js/prettify.js"></script>
	<script type="text/javascript" src="js/slides.min.jquery.js"></script>
	<script type="text/javascript">
	function modifMenu(ancre){
		$("#menu a").each(function(){
			if($(this).attr("href") == ancre){
				$(this).addClass("current");
			}else{
				$(this).removeClass("current");
			}
		});
	}
	$("document").ready(function() {
		$('a').click(function(){
			var $anchor = $(this);
			modifMenu($anchor.attr('href'));
			$('html, body').animate({
				scrollTop:  ($($anchor.attr('href')).offset().top-115)
			}, 2000);
		});
	});
	
	function scroll(e){
		var scrollTop = $(window).scrollTop()+100;
		var tab = ["Accueil", "Apercu", "Fonctionnalites", "Navigation", "Documentation" ];
		for(var i= 0; i < tab.length; i++){
			var txt = "#"+tab[i];
			var tmp = $(txt);
			if(i==2){
				console.log(txt + " " + tmp.position().top + " " + tmp.height() + " " + scrollTop);
			}
			if((tmp.position().top < scrollTop) && (tmp.position().top + tmp.height() > scrollTop)){
				
				modifMenu(txt);
			}
		}
	}
	 
	var mousewheelevt=(/Firefox/i.test(navigator.userAgent))? "DOMMouseScroll" : "mousewheel" //FF doesn't recognize mousewheel as of FF3.x
	 
	if (window.attachEvent) //if IE (and Opera depending on user setting)
		window.attachEvent("on"+mousewheelevt, scroll)
	else if (window.addEventListener) //WC3 browsers
		window.addEventListener(mousewheelevt, scroll, false)
	</script>
</head>
<body onload="prettyPrint()">
	<div id="page">
		<div id="conteneurHeader" style="position:fixed; z-index:1000;">
			<div id="sousConteneurHeader">
				<div id="header">
					<img src="css/fileExplorer.png" id="fileExplorerIcone" alt="File Explorer">
					<div id="menu">
						<a href="#Accueil" class="current" >Accueil</a>
						<a href="#Apercu">Aperçu</a>
						<a href="#Fonctionnalites">Fonctionnalités</a>
						<a href="#Navigation">Navigation</a>
						<a href="#Documentation" >Documentation</a>
					</div>
				</div>
			</div>
			<div class="ombrageHeader"></div>
		</div>
		<div id="main">
			<div id="Accueil">
			<h3>PANERI Jérémy<br/>
				TISSOT Arthur</h3>
				<h1>
					Rapport du micro-projet 2 de MICA : RCP
					<br />
					L’explorateur de fichier
					<br />
					<br />
					<img src="css/splash.bmp" alt="splashScreen" width="455" height="295" />
				</h1>

			</div>
			<div id="Apercu">
				<h2>Aperçu de l'application</h2>
				<center><br/><img src="css/apercu.png" alt="apercu" width="630" height="500" /></center>
				<p>
					Le deuxième projet de MICA a pour but de nous apprendre à développer une application RCP (Rich Client Platform), c'est-à-dire basée sur le noyau et les bibliothèques Eclipse. Le programme souhaité est un explorateur de fichiers (semblable à l'explorateur Windows ou au Finder de Mac OS) devant permettre à l'utilisateur de se déplacer dans l'arborescence de son disque dur et d'effectuer quelques actions basiques.
				</p>
				<p>
					Notre application utilise des composants SWT pour son interface graphique, et dispose de nombreuses fonctionnalités comme par exemple une double navigation, la gestion du presse-papiers ou encore le changement de taille des icônes affichées. La plupart d'entre elles sont détaillées dans la suite de ce document, avec en premier lieu un point de vue «utilisateur» puis avec des exemples plus techniques et spécifiques à la vue en icônes.
				</p>
			</div>

				<br/>
				
			<div id="Fonctionnalites">
				<h2>Fonctionnalités implémentées</h2>
				<h3>Double navigation</h3>
				<p>
					Le cœur visuel de notre application se divise en deux parties. Dans la colonne de gauche se trouve la navigation en arbre : elle permet, via des dossiers à dérouler, de naviguer rapidement parmi les éléments de l'arborescence du disque dur.
				</p>
				<p>
					La vue principale est celle sous forme d'icônes et est l'élément central de notre application. Elle permet de repérer plus distinctement et facilement les différents éléments d'un dossier et de les manipuler.
				</p>
				<h3>Ouverture d'éléments</h3>
				<p>
					Ouvrir un dossier au sein même de notre explorateur peut se faire de deux manières : soit en le sélectionnant dans la colonne d'arbre, soit en double-cliquant depuis la vue en icônes. Pour ouvrir un fichier avec son application par défaut, il suffit de double-cliquer dessus dans la vue en icônes.
				</p>
				<h3>Types de fichiers</h3>
				<p>
					Afin d'améliorer le repérage visuel de l'utilisateur, chaque type de d'élément possède sa propre icône d'aperçu. Elles apparaissent dans chacune des deux vues et concernent les dossiers, images, musiques, vidéos, PDF, textes, et fichiers web, avec une icône générique pour les autres types.
				</p>
				<h3>Internationalisation</h3>
				<p>
					La langue de notre programme s'adapte automatiquement à la langue actuelle utilisée par Eclipse. Tous les éléments textuels sont donc disponibles à la fois en anglais et en français.
				</p>
				<h3>Presse-papiers</h3>
				<p>
					Notre application implémente les fonctionnalités du presse-papiers système, via le menu ou un clic droit. Il est ainsi possible de copier, couper ou coller un fichier en passant indiféremment par l'interface ou un programme externe, dans les deux sens comme en interne.
				</p>
				<center><img src="css/captureMenuContextuel.jpg" width="274" height="186" alt="Capture d'écran du menu contextuel" /></center>
				<h3>Renommer</h3>
				<p>
					L'utilisateur a également la possibilité de renommer n'importe quel fichier depuis notre explorateur. Là encore via le menu ou un clic droit, une boîte de dialogue s'ouvre afin de permettre la saisie du nom souhaité.
				</p>
				<center><img src="css/capturePopupRenommer.jpg" width="402" height="116" alt="capture d'écran : popup renommer" /></center>
				<h3>Supprimer</h3>
				<p>
					La suppression d'un fichier ou dossier est disponible en effectuant un clic droit : elle doit par sécurité être confirmée par l'utilisateur dans une boîte de dialogue. Il est possible de supprimer plusieurs éléments à la fois via la sélection multiple.
				</p>
				<center><img src="css/capturePopupSupprimer.jpg" width="392" height="116" alt="capture d'écran : voulez-vous vraiment supprimer ce fichier?" /></center>

				<h3>Propriétés</h3>
				<p>
					Dans le menu contextuel, une option "Propriétés" permet l'affichage de différentes informations sur le fichier ou dossier : son nom, sa date, sa taille, son type et ses droits.<br />
				</p>
				<p>
					Nous avons pas réalisé le calcul de la taille d'un dossier : cela suggérait de faire un parcours récursif dans chaque fichier et sous-dossier qu'il contient, or cette manipulation peut être particulièrement longue pour l'utilisateur.
				</p>
				<center><img src="css/capturePopupProprietes.jpg" width="258" height="203" alt="captures d'écran avec des tailles d'icones différentes" /></center>
			</div>
				
				<br/>
				
			<div id="Navigation" >
				<h2>Navigation en icônes</h2>
				<h3>Interface spécifique</h3>
				<p>
					En prenant comme base le composant «Canvas» inclus dans SWT, nous avons recréé une interface graphique à la fois ergonomique et esthétique. Nous avons voulu présenter les fichiers et dossiers sous formes d'icônes alignées, tout en rendant ce composant suffisamment généraliste afin de pouvoir le réutiliser dans d'autres applications à l'avenir.
				</p>
				<h3>Placement des icônes</h3>
				<p>
					Afin d'éviter d'avoir une barre de défilement horizontale peu pratique à utiliser, nous nous sommes limités à une verticale : les éléments sont affichés de gauche à droite, puis iront automatiquement à la ligne une fois arrivé au bout de la fenêtre.
				</p>
				<h3>Modification de leur taille</h3>
				<p>
					La taille des icônes peut être modifiée à l'aide du curseur présent en bas de la fenêtre. Si celle-ci est inférieure à 32 pixels, alors elle reste centrée afin que le texte soit toujours lisible.
				</p>
				<center><img src="css/captureTailleIcone.jpg" width="557" height="243" alt="captures d'écran avec des tailles d'icones différentes" /></center>
				<h3>Affichage du nom</h3>
				<p>
					Le nom d'un élément est toujours affiché de manière centrée par rapport à son icône. S'il est trop long, alors on affiche seulement ses premiers caractères, deux points puis ses quatre derniers caractères. Par exemple un fichier s'appelant «nom_de_fichier_tres_long» s'afficherait sous la forme «nom_d..long».
				</p>
				<p>
					La police d'affichage n'étant pas à chasse fixe, nous avons dû faire appel à une méthode particulière de «GC» nous permettant de centrer le texte en tenant compte de la largeur de chaque caractère.
				</p>
<pre class="prettyprint linenums">
Point sizeStrNom = gc.textExtent(afficheNom);
int mid = widthObject/2 - sizeStrNom.x/2;

// On ajoute le texte
gc.drawText(afficheNom, fileObject.getX() + origin.x + mid, fileObject.getY()
	+ origin.y + tailleIcon);
</pre>
				<h3>Création des écouteurs</h3>
				<p>	
					Spécialement pour cette vue, nous avons dû créer plusieurs écouteurs (listeners) en suivant le pattern Observer.<br />
					1. Le simple clic permet de sélectionner ur élément ;<br />
					2. Le double clic permet d'ouvrir un dossier ou un fichier ;<br />
					3. Le glisser-déposer permet de déplacer des éléments sur le disque.<br />
				</p>
<pre class="prettyprint linenums">
public interface DragAndDropListener {
	public void drag(ArrayList<FileObject> source, FileObject dest);
}
</pre>
<pre class="prettyprint linenums">
public class FileIconView extends Canvas implements MouseListener {
	ArrayList<DragAndDropListener> dragAndDropListener;

	public FileIconView(Composite parent, int style) {
		super(parent, style);
		doubleClickOnFileListener = new ArrayList<ClickOnFileListener>();
	}

	public void addDragAndDropListener(DragAndDropListener dragAndDropListener) {
		this.dragAndDropListener.add(dragAndDropListener);
	}

	public boolean removeDragAndDropListener(DragAndDropListener dragAndDropListener) {
		return this.dragAndDropListener.remove(dragAndDropListener);
	}

	@Override
	public void mouseUp(MouseEvent e) {
		// [...] "source" et "dest" sont définis ici
		// Lorsque le clic est relâché, on effectue les actions
		// sur tous les fichiers actuellement sélectionnés
		for (int i = 0; i < dragAndDropListener.size(); i++) {
			dragAndDropListener.get(i).drag(source, dest);
		}
		// [...]
	}
}
</pre>
				<h3>Sélection multiple</h3>
				<p>
					La vue en icônes offre la possibilité à l’utilisateur de faire une sélection multiple, c'est-à-dire de manipuler plusieurs fichiers ou dossiers à la fois. Pour cela, il doit maintenir la touche contrôle «CTRL» enfoncée lors de son clic.
				</p>
				<h3>Glisser-déposer</h3>
				<p>
					Gérer le glisser-déposer (drag & drop) nous a demandé la gestion de deux évènements souris en simultané : savoir si l'utilisateur garde le clic enfoncé, et s'il déplace son curseur. De plus, il faut repérer correctement les points de départ et d'arrivée afin que le déplacement visuel se fasse sans rupture.
				</p>
				<p>
					Cette fonctionnalité permet à l'utilisateur de changer l'emplacement de ses fichiers sur le disque dur, pour les passer d'un dossier à un autre, de manière visuelle et intuitive.
				</p>
				<h3>Double buffer</h3>
				<p>
					Pour éviter que l’écran ne clignote lors du glissement d'un élément et que sa trace reste visible, le rafraîchissement utilise la technique du double buffer : le composant est d’abord mis sous la forme d’une image, et n’est affiché que lorsque sa création est terminée.
				</p>
<pre class="prettyprint linenums">
// FileIconView.java
public void paintControl(PaintEvent e) {
	// Taille de la vue
	Point tailleView = getSize();
	Image img = new Image(getDisplay(), tailleView.x, tailleView.y);
	// Outils pour pouvoir dessiner dans l'image
	GC gc = new GC(img);

	// [...] Réalise le dessin de la vue

	// Termine le dessin
	gc.dispose();
	// On peut maintenant coller notre image dans la vue
	GC gc2 = new GC(this);
	gc2.drawImage(img, 0, 0, tailleView.x, tailleView.y, 0, 0, tailleView.x, tailleView.y);
	gc2.dispose();
}
</pre>
			<h3>Tri par type</h3>
			<p>
				La vue en icônes est composée d'objets «FileObject» : cette classe implémente l'interface «Comparable», et possède donc la méthode «compareTo» permettant de trier les éléments entre eux.
			</p>
			<p>
				Par défaut, la vue en icône utilise cette méthode pour trier les fichiers entres eux, mais il est également possible de changer le type de tri que la vue utilise en utilisant la méthode "setTypeDeTri".
			</p>
<pre class="prettyprint linenums">
// FileObject.java
@Override
public int compareTo(FileObject fileObject) {
	if(this.nature==NatureFile.dossier) {
		if(fileObject.getNature()==NatureFile.fichier) {
			return -1;
		}
	}
	else {
		if(fileObject.getNature()==NatureFile.dossier) {
			return 1;
		}
	}
	return nom.compareTo(fileObject.getNom());
}
</pre>
<pre class="prettyprint linenums">
// FileIconView.java
private Comparator<FileObject> typeDeTri=null;

public void refrechPosition() {
	// Par défaut
	if(typeDeTri==null) {
		// On ordonne les items par ordre alphabétique et par type :
		// en premier les dossiers puis les fichiers
		Collections.sort(filesObject);
	}
	else {
		Collections.sort(filesObject, typeDeTri);
	}
	// [...] Modifie la position de chaque fichier selon leur place dans la liste
}

public void setTypeDeTri(Comparator<FileObject> typeDeTri) {
	this.typeDeTri = typeDeTri;
	refreshPosition();
}
</pre>
				
				<h3>Miniatures des images</h3>
				<p>
					L'affichage d'un aperçu des images à la place de l'icône générique était une fonctionnalité intéressante, mais s'avère gourmande en ressource : lorsqu'il y a beaucoup d'images dans un même dossier, cela ralentit considérablement l'exécution du programme. Cette fonctionnalité n'a donc pas été implémentée.<br />
				</p>
			</div>
				<br/>
				
			<div id="Documentation" >
				<h2>Documentation technique</h2>
				<p>
					La documentation technique de notre application a été générée automatiquement depuis Eclipse, à partir des informations contenues dans notre code source. Elle contient une description de toutes les classes, interfaces et méthodes utilisées.
				</p>
				<p><a href="javadoc/index.html">Consulter la JavaDoc ici.</a></p>
			</div>
		</div>

		<div id="footer">
			<div id="contentfooter">
				<div class="tache"></div>
				<table class="tabBottom">
					<tbody>
						<tr>
							<td width="50%">
								<div class="tabContent">
									Master 1 Informatique<br />
									Université de Franche-Comté
								</div>
							</td>
							<td width="50%">
								<div class="tabContent">
									File Explorer - Micro-projet de MICA<br />
									PANERI Jérémy - TISSOT Arthur
								</div>
							</td>
						</tr>
					</tbody>
				</table>
				<br /><br />
			</div>
		</div>
	</div>
</body>
</html>
